home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / graphics / povray2.zip / SOURCE / IFF.C < prev    next >
C/C++ Source or Header  |  1993-09-12  |  10KB  |  353 lines

  1. /****************************************************************************
  2. *                   iff.c
  3. *
  4. *  This file implements a simple IFF format file reader.
  5. *
  6. *  from Persistence of Vision Raytracer
  7. *  Copyright 1993 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  NOTICE: This source code file is provided so that users may experiment
  10. *  with enhancements to POV-Ray and to port the software to platforms other 
  11. *  than those supported by the POV-Ray Team.  There are strict rules under
  12. *  which you are permitted to use this file.  The rules are in the file
  13. *  named POVLEGAL.DOC which should be distributed with this file. If 
  14. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  15. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  16. *  Forum.  The latest version of POV-Ray may be found there as well.
  17. *
  18. * This program is based on the popular DKB raytracer version 2.12.
  19. * DKBTrace was originally written by David K. Buck.
  20. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  21. *
  22. *****************************************************************************/
  23.  
  24. #include "frame.h"
  25. #include "povproto.h"
  26.  
  27. static IMAGE_COLOUR *iff_colour_map;
  28. static int colourmap_size;
  29. static CHUNK_HEADER Chunk_Header;
  30.  
  31. #define FORM 0x464f524dL
  32. #define ILBM 0x494c424dL
  33. #define BMHD 0x424d4844L
  34. #define CAMG 0x43414d47L
  35. #define CMAP 0x434d4150L
  36. #define BODY 0x424f4459L
  37. #define CMPNONE 0
  38.  
  39. #define HAM 0x800
  40.  
  41. void iff_error()
  42.   {
  43.   fprintf (stderr, "Invalid IFF file\n");
  44.   exit(1);
  45.   }
  46.  
  47. int read_byte(f)
  48. FILE *f;
  49.   {
  50.   int c;
  51.   if ((c = getc(f)) == EOF)
  52.     iff_error();
  53.   return (c);
  54.   }
  55.  
  56. int read_word(f)
  57. FILE *f;
  58.   {
  59.   int result;
  60.  
  61.   result = read_byte(f)*256;
  62.   result += read_byte(f);
  63.   return (result);
  64.   }
  65.  
  66. long read_long(f)
  67. FILE *f;
  68.   {
  69.   int i;
  70.   long result;
  71.  
  72.   result = 0;
  73.   for (i = 0 ; i < 4 ; i++)
  74.     result = result * 256 + read_byte(f);
  75.  
  76.   return (result);
  77.   }
  78.  
  79. void Read_Chunk_Header (f, dest)
  80. FILE *f;
  81. CHUNK_HEADER *dest;
  82.   {
  83.   dest->name = read_long(f);
  84.   dest->size = read_long(f);
  85.   }
  86.  
  87. void Read_Iff_Image(Image, filename)
  88. IMAGE *Image;
  89. char *filename;
  90.   {
  91.   FILE *f;
  92.   unsigned char **row_bytes;
  93.   int c, i, j, k, nBytes, nPlanes, compression,
  94.   mask, byte_index, count, viewmodes;
  95.   int Previous_Red, Previous_Green, Previous_Blue;
  96.   struct Image_Line *line;
  97.   unsigned long creg;
  98.  
  99.   if ((f = Locate_File(filename, READ_FILE_STRING)) == NULL) 
  100.     {
  101.     fprintf (stderr, "Cannot open IFF file %s\n", filename);
  102.     exit(1);
  103.     }
  104.  
  105.   Previous_Red = Previous_Green = Previous_Blue = 0;
  106.  
  107.   viewmodes = 0;
  108.   iff_colour_map = NULL;
  109.  
  110.   while (1) 
  111.     {
  112.     Read_Chunk_Header(f, &Chunk_Header);
  113.     switch ( IFF_SWITCH_CAST Chunk_Header.name) 
  114.     {
  115.     case FORM:  
  116.       if (read_long(f) != ILBM)
  117.         iff_error();
  118.       break;
  119.  
  120.     case BMHD:  
  121.       Image->iwidth = read_word(f);
  122.       Image->width = (DBL)Image->iwidth;
  123.       Image->iheight = read_word(f);
  124.       Image->height = (DBL)Image->iheight;
  125.  
  126.       read_word(f);  /* x position ignored */
  127.       read_word(f);  /* y position ignored */
  128.       nPlanes = read_byte(f);
  129.       colourmap_size = 1<<nPlanes;
  130.       read_byte(f);   /* masking ignored */
  131.       compression = read_byte(f);   /* masking ignored */
  132.       read_byte(f);   /* pad */
  133.       read_word(f);   /* Transparent colour ignored */
  134.       read_word(f);   /* Aspect ratio ignored */
  135.       read_word(f);   /* page width ignored */
  136.       read_word(f);   /* page height ignored */
  137.       break;
  138.  
  139.     case CAMG:  
  140.       viewmodes = (int) read_long(f);   /* Viewmodes */
  141.       if (viewmodes & HAM)
  142.         colourmap_size = 16;
  143.  
  144.       break;
  145.  
  146.     case CMAP:  
  147.       colourmap_size = (int) Chunk_Header.size / 3;
  148.  
  149.       if ((iff_colour_map = (IMAGE_COLOUR *) malloc(sizeof(IMAGE_COLOUR)*colourmap_size)) == NULL) 
  150.         {
  151.         fprintf(stderr, "Cannot allocate memory for IFF colour map\n");
  152.         exit(1);
  153.         }
  154.  
  155.       for (i = 0 ; i < colourmap_size ; i++) 
  156.         {
  157.         iff_colour_map[i].Red = read_byte(f);
  158.         iff_colour_map[i].Green = read_byte(f);
  159.         iff_colour_map[i].Blue = read_byte(f);
  160.         iff_colour_map[i].Filter = 0;
  161.         }
  162.  
  163.       Previous_Red = iff_colour_map[0].Red;
  164.       Previous_Green = iff_colour_map[0].Green;
  165.       Previous_Blue = iff_colour_map[0].Blue;
  166.       for (i = colourmap_size * 3 ; (long) i < Chunk_Header.size ; i++)
  167.         read_byte(f);
  168.  
  169.       break;
  170.  
  171.     case BODY:  
  172.       if ((iff_colour_map == NULL) || (viewmodes & HAM)) 
  173.         {
  174.         Image->Colour_Map_Size = 0;
  175.         Image->Colour_Map = NULL;
  176.         }
  177.       else 
  178.         {
  179.         Image->Colour_Map_Size = colourmap_size;
  180.         Image->Colour_Map = iff_colour_map;
  181.         }
  182.  
  183.         if ((row_bytes = (unsigned char **) malloc (4*nPlanes)) == NULL) 
  184.         {
  185.         fprintf (stderr, "Cannot allocate memory for row bytes\n");
  186.         exit(1);
  187.         }
  188.  
  189.       for (i = 0 ; i < nPlanes ; i++)
  190.         if ((row_bytes[i] = (unsigned char *)
  191.           malloc(((Image->iwidth+15)/16)*2)) == NULL)
  192.         {
  193.         fprintf (stderr, "Cannot allocate memory for row bytes\n");
  194.         exit(1);
  195.         }
  196.  
  197.       if (Image->Colour_Map == NULL) 
  198.         {
  199.         if ((Image->data.rgb_lines = (struct Image_Line *)
  200.           malloc(Image->iheight * sizeof (struct Image_Line)))==NULL) 
  201.           {
  202.           fprintf (stderr, "Cannot allocate memory for picture\n");
  203.           exit(1);
  204.           }
  205.         }
  206.       else 
  207.         {
  208.         if ((Image->data.map_lines = (unsigned char **)
  209.           malloc(Image->iheight * sizeof (unsigned char *)))==NULL) 
  210.           {
  211.           fprintf (stderr, "Cannot allocate memory for picture\n");
  212.           exit(1);
  213.           }
  214.         }
  215.  
  216.       for (i = 0 ; i < Image->iheight ; i++) 
  217.         {
  218.  
  219.         if (Image->Colour_Map == NULL) 
  220.           {
  221.           if (((Image->data.rgb_lines[i].red = (unsigned char *)
  222.             malloc(Image->iwidth))==NULL) ||
  223.             ((Image->data.rgb_lines[i].green = (unsigned char *)
  224.             malloc(Image->iwidth))==NULL) ||
  225.             ((Image->data.rgb_lines[i].blue = (unsigned char *)
  226.             malloc(Image->iwidth))==NULL)) 
  227.             {
  228.             fprintf (stderr, "Cannot allocate memory for picture\n");
  229.             exit(1);
  230.             }
  231.           }
  232.         else 
  233.           {
  234.           if ((Image->data.map_lines[i] = (unsigned char *)
  235.             malloc(Image->iwidth * sizeof(unsigned char))) == NULL) 
  236.             {
  237.             fprintf (stderr, "Cannot allocate memory for picture\n");
  238.             exit(1);
  239.             }
  240.           }
  241.  
  242.         for (j = 0 ; j < nPlanes ; j++)
  243.           if (compression == CMPNONE) 
  244.           {
  245.           for (k = 0 ; k < (((Image->iwidth+15)/16)*2) ; k++)
  246.             row_bytes[j][k] = (unsigned char)read_byte(f);
  247.           if ((k & 1) != 0)
  248.             read_byte(f);
  249.           }
  250.  
  251.           else 
  252.           {
  253.           nBytes = 0;
  254.           while (nBytes != ((Image->iwidth+15)/16)*2)
  255.             {
  256.             c = read_byte(f);
  257.             if ((c >= 0) && (c <= 127))
  258.               for (k = 0 ; k <= c ; k++)
  259.               row_bytes[j][nBytes++] = (unsigned char)read_byte(f);
  260.             else if ((c >= 129) && (c <= 255)) 
  261.               {
  262.               count = 257-c;
  263.               c = read_byte(f);
  264.               for (k = 0 ; k < count ; k++)
  265.                 row_bytes[j][nBytes++] = (unsigned char)c;
  266.               }
  267.             }
  268.           }
  269.  
  270.         mask = 0x80;
  271.         byte_index = 0;
  272.         for (j = 0 ; j < Image->iwidth ; j++) 
  273.           {
  274.           creg = 0;
  275.           for (k = nPlanes-1 ; k >= 0 ; k--)
  276.             if (row_bytes[k][byte_index] & mask)
  277.               creg = creg*2 + 1;
  278.             else
  279.               creg *= 2;
  280.  
  281.  
  282.           if (viewmodes & HAM) 
  283.             {
  284.             line = &Image->data.rgb_lines[i];
  285.             switch (creg >> 4) 
  286.             {
  287.             case 0:
  288.               Previous_Red = line->red[j] = (unsigned char)iff_colour_map[creg].Red;
  289.               Previous_Green = line->green[j] = (unsigned char)iff_colour_map[creg].Green;
  290.               Previous_Blue = line->blue[j] = (unsigned char)iff_colour_map[creg].Blue;
  291.               break;
  292.  
  293.             case 1:
  294.               line->red[j] = (unsigned char)Previous_Red;
  295.               line->green[j] = (unsigned char)Previous_Green;
  296.               line->blue[j] = (unsigned char)(((creg & 0xf)<<4) + (creg&0xf));
  297.               Previous_Blue = (int) line->blue[j];
  298.               break;
  299.  
  300.             case 2:
  301.               line->red[j] = (unsigned char)(((creg & 0xf)<<4) + (creg&0xf));
  302.               Previous_Red = (int) line->red[j];
  303.               line->green[j] = (unsigned char)Previous_Green;
  304.               line->blue[j] = (unsigned char)Previous_Blue;
  305.               break;
  306.  
  307.             case 3:
  308.               line->red[j] = (unsigned char)Previous_Red;
  309.               line->green[j] = (unsigned char)(((creg & 0xf)<<4) + (creg&0xf));
  310.               Previous_Green = (int) line->green[j];
  311.               line->blue[j] = (unsigned char)Previous_Blue;
  312.               break;
  313.             }
  314.             }
  315.           else if (nPlanes == 24) 
  316.             {
  317.             line = &Image->data.rgb_lines[i];
  318.             line->red[j] = (unsigned char)((creg >> 16) & 0xFF);
  319.             line->green[j] = (unsigned char)((creg >> 8) & 0xFF);
  320.             line->blue[j] = (unsigned char)(creg & 0xFF);
  321.             }
  322.           else 
  323.             {
  324.             if (creg > (unsigned long)Image->Colour_Map_Size) 
  325.               {
  326.               fprintf (stderr, "Error - IFF Image Map Colour out of range\n");
  327.               exit(1);
  328.               }
  329.             Image->data.map_lines[i][j] = (char)creg;
  330.             }
  331.  
  332.           mask >>= 1;
  333.           if (mask == 0) 
  334.             {
  335.             mask = 0x80;
  336.             byte_index++;
  337.             }
  338.           }
  339.         }
  340.  
  341.       free (row_bytes);
  342.       fclose (f);
  343.       return;
  344.  
  345.     default:
  346.       for (i = 0 ; (long) i < Chunk_Header.size ; i++)
  347.         if (getc(f) == EOF)
  348.           iff_error();
  349.       break;
  350.     }
  351.     }
  352.   }
  353.